package com.renu.jdependencyanalyser.soot;

import com.renu.jdependencyanalyser.core.ProjectBorderGene;
import com.renu.jdependencyanalyser.core.ProjectInfo;
import com.renu.jdependencyanalyser.utils.MyProjectUtil;
import soot.*;
import soot.util.Chain;

import java.util.HashSet;
import java.util.Map;

@Deprecated
public class MyAnalysisTransformer extends SceneTransformer {

    private ProjectInfo projectInfo;

    private ProjectBorderGene projectBorderGene;

    public MyAnalysisTransformer(ProjectInfo projectInfo, ProjectBorderGene projectBorderGene) {
        this.projectInfo = projectInfo;
        this.projectBorderGene = projectBorderGene;
    }

    public ProjectInfo getProjectInfo() {
        return projectInfo;
    }

    public void setProjectInfo(ProjectInfo projectInfo) {
        this.projectInfo = projectInfo;
    }

    @Override
    protected void internalTransform(String phaseName, Map<String, String> options) {
        Chain<SootClass> sootClasses = Scene.v().getApplicationClasses();
        System.out.println("loading project begins...");

        HashSet<SootMethod> sootMethods = new HashSet<>();
        HashSet<SootField> mySootFields = new HashSet<>();
        HashSet<SootMethod> mySootMethod = new HashSet<>();

        projectBorderGene.buildInnerClass();


        for (SootClass sootClass : sootClasses) {
            if(!MyProjectUtil.isJDKClassOrBasicType(sootClass.getName())){

                // class
                //
                projectInfo.setOrAddClass(sootClass);
                // package
                //String packageName = sootClass.getPackageName();
                //PackageModel packageModel = new PackageModel(ProjectCons.PROJECT_SELF_NAME ,packageName);
                //this.addPck(packageModel);
                //this.classBindPck(sootClass.getName(),packageModel.getPckSig());
                //this.pckBindJar(packageModel.getPckSig(),ProjectCons.PROJECT_SELF_NAME);

                // method
                for (SootMethod method : sootClass.getMethods()) {
                    if (projectBorderGene.getProjectClasses().contains(sootClass.getName())){
                        mySootMethod.add(method);
                    }

                    projectInfo.addMethod(method);
                    projectInfo.methodBindClass(method.getSignature(),sootClass.getName());
                    sootMethods.add(method);

                }
                // field
                for (SootField field : sootClass.getFields()) {
                    if (projectBorderGene.getProjectClasses().contains(sootClass.getName())){
                        mySootFields.add(field);
                    }
                    projectInfo.addField(field);
                    projectInfo.fieldBindClass(field.getSignature(),sootClass.getName());
                    //sootFields.add(field);
                }
            }

        }

        // myfield bind to type
        for (SootField sootField : mySootFields) {
            String typeString = MyProjectUtil.type2String(sootField.getType());
            projectInfo.fieldBindType(sootField.getSignature(),typeString);
        }

        //
        // Mymedthod bind localTYypes
        for ( SootMethod sootMethod : mySootMethod) {
            if (sootMethod.isAbstract())
                continue;
            Chain<Local> locals = sootMethod.retrieveActiveBody().getLocals();
            for (Local local : locals) {
                String typeString = MyProjectUtil.type2String(local.getType());
                projectInfo.methodBindLocals(sootMethod.getSignature(),typeString);
            }
        }

        projectBorderGene.buildInvokeRelation(mySootMethod,sootMethods);





        System.out.println("loadinh project ends");
    }
}
